/*
  Part of the MasterTool3D project - http://code.google.com/p/master-tool-3d

  Copyright (c) 2011 Ingo Pueschl

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation, version 2.1.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

package techjit.gfx.core;

import processing.core.PApplet;
import techjit.gfx.util.PU;
import techjit.gfx.util.geo.Dimensions;
import techjit.gfx.util.geo.Vector;
import techjit.util.LogManager;
import techjit.util.RuntimeParams;

public class GFX_LineLayout extends GFX_Layout {

	// FIELDS
	private int lineLayoutId;
	private static int nextLineLayoutId = RuntimeParams.GFX__FIRST_ID;

	// CONSTRUCTORS
	public GFX_LineLayout(GFX_Scene rootScene) {
		// head
		super(rootScene);
		lineLayoutId = nextLineLayoutId++;

		// tail
		logConstructorResult();
	}

	@Override
	protected void arrange() {
		// head
		logArrangementInvocation();

		// arrange
		arrange_arrangeElements();

		// dimensions
		arrange_determineLocalDimensions();

		// // translate
		// arrange_translateElements();

		// determine relDims
		super.arrange();

		// tail
		logLocalArrangementResult();
	}

	// METHODS
	private void arrange_arrangeElements() {
		for (GFX_SceneElement element : elements) {
			element.arrange();
		}
	}

	private void arrange_determineLocalDimensions() {
		if (elements.isEmpty()) {
			changeLocalDimensions(new Dimensions(4, 5, 6));
		} else {
			float layoutWidth = 0;
			float layoutHeight = 0;
			float layoutDepth = 0;
			for (GFX_SceneElement element : elements) {
				layoutWidth += element.relDims.getWidth();
				layoutHeight = PApplet.max(layoutHeight,
						element.relDims.getHeight());
				layoutDepth = PApplet.max(layoutDepth,
						element.relDims.getDepth());
			}

			changeLocalDimensions(new Dimensions(layoutWidth, layoutHeight,
					layoutDepth));
		}
	}

	@Override
	protected void draw(PApplet p) {
		// Push local (relative for scenes) coordinate system matrix of parent
		// to stack.
		p.pushMatrix();
		{
			// Move to origin of relative coordinate system in GFX_Object,
			// rotate and move to rotation offset in GFX_SceneElement.
			super.draw(p);

			// Draw children at rotated local coordinate system of this line
			// layout.
			draw_drawElements(p);
		}

		// Retrieve local (relative for scenes) coordinate system matrix for
		// parent.
		p.popMatrix();
	}

	private void draw_drawElements(PApplet p) {
		float layoutHeight = localDims.getHeight();
		float layoutDepth = localDims.getDepth();
		for (GFX_SceneElement element : elements) {
			float elementWidth = element.relDims.getWidth();
			float elementHeight = element.relDims.getHeight();
			float elementDepth = element.relDims.getDepth();
			float deltaHeight = layoutHeight - elementHeight;
			float deltaDepth = layoutDepth - elementDepth;

			switch (alignmentY) {
			case CENTER:
				PU.translate(p, new Vector(0, deltaHeight / 2, 0));
				break;
			case REMOTE:
				PU.translate(p, new Vector(0, deltaHeight, 0));

				break;
			}
			switch (alignmentZ) {
			case CENTER:
				PU.translate(p, new Vector(0, 0, deltaDepth / 2));

				break;
			case REMOTE:
				PU.translate(p, new Vector(0, 0, deltaDepth / 2));

				break;
			}

			element.draw(p);

			switch (alignmentY) {
			case CENTER:
				PU.translate(p, new Vector(0, -deltaHeight / 2, 0));
				break;
			case REMOTE:
				PU.translate(p, new Vector(0, -deltaHeight, 0));

				break;
			}
			switch (alignmentZ) {
			case CENTER:
				PU.translate(p, new Vector(0, 0, -deltaDepth / 2));

				break;
			case REMOTE:
				PU.translate(p, new Vector(0, 0, -deltaDepth / 2));

				break;
			}

			PU.translate(p, new Vector(elementWidth, 0, 0));
		}

	}

	@Override
	public void log() {
		LogManager.logALL("" + this);
		LogManager.indent();
		{
			super.log();
		}
		LogManager.deindent();
	}

	@Override
	public String toString() {
		return "<GFX_LineLayout " + lineLayoutId + ">";
	}

	// @Override
	// protected void translate(Vector v) {
	// // super.translate(v);
	//
	// for (GFX_SceneElement element : elements) {
	// element.translate(v);
	// }
	//
	// }

}
